namespace Chaliy.Syndication
{
	using System;
	using System.Xml;
    using System.Runtime.Serialization;
    using System.Reflection;
    using System.Xml.Serialization;
	
	internal static class XmlWriterExtensions
    {
        public static void WriteBooleanAttribute(this XmlWriter writer, string localName, bool value)
        {
            ArgumentUtilities.EnsureArgumentNotNull(writer, "writer");

            if (value)
            {
                writer.WriteAttributeString(localName, XmlConvert.ToString(value));
            }
        }

        public static void WriteDoubleAttribute(this XmlWriter writer, string localName, double? value)
        {
            ArgumentUtilities.EnsureArgumentNotNull(writer, "writer");

            if (value.HasValue)
            {
                writer.WriteAttributeString(localName, XmlConvert.ToString(value.Value));
            }
        }

        public static void WriteInt32Attribute(this XmlWriter writer, string localName, int? value)
        {
            ArgumentUtilities.EnsureArgumentNotNull(writer, "writer");

            if (value.HasValue)
            {
                writer.WriteAttributeString(localName, XmlConvert.ToString(value.Value));
            }
        }

        public static void WriteStringAttribute(this XmlWriter writer, string localName, string value)
        {
            ArgumentUtilities.EnsureArgumentNotNull(writer, "writer");

            if (String.IsNullOrEmpty(value) == false)
            {
                writer.WriteAttributeString(localName, value);
            }
        }

        public static void WriteEnumAttribute<TEnum>(this XmlWriter writer, string localName, TEnum enumValue)
        {
            ArgumentUtilities.EnsureArgumentNotNull(writer, "writer");

            Type enumType = typeof(TEnum);

            if (Enum.IsDefined(enumType, enumValue) == false)
            {
                SerializationException enumIsNotDefinedException
                    = new SerializationException(Resources.EnumValueIsNotDefined);

                enumIsNotDefinedException.Data["Type"] = enumType.FullName;
                enumIsNotDefinedException.Data["Value"] = enumValue;

                throw enumIsNotDefinedException;
            }

            string enumName = Enum.GetName(enumType, enumValue);
            FieldInfo enumField = enumType.GetField(enumName);

            XmlEnumAttribute enumXmlAttribute = new XmlAttributes(enumField).XmlEnum;
            string name = enumXmlAttribute != null
                            ? enumXmlAttribute.Name
                            : enumName;

            if ("None".Equals(name, StringComparison.OrdinalIgnoreCase) == false)
            {
                writer.WriteAttributeString(localName, name);
            }
        }

        public static void WriteEnumAttribute<TEnum>(this XmlWriter writer, string localName, TEnum enumValue, TEnum defaultValue)
        {
            if (enumValue.Equals(defaultValue) == false)
            {
                WriteEnumAttribute<TEnum>(writer, localName, enumValue);
            }
        }

        public static void WriteExtension(this XmlWriter writer, object extension)
        {
            ArgumentUtilities.EnsureArgumentNotNull(writer, "writer");
            ArgumentUtilities.EnsureArgumentNotNull(extension, "extension");

            DataContractSerializer serializer 
                = new DataContractSerializer(extension.GetType());

            serializer.WriteObject(writer, extension);
        }
    }
}
